/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2002, GeoVISTA Center
 * Licensed under Simplified BSD License
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
*
*
* @author: jin Chen
* @date: Nov 12, 2004$
* @version: 1.0
*/
package edu.psu.geovista.app.pcp.plot.control;

import edu.psu.geovista.app.pcp.plot.control.tools.AxisShowRangeTool;
import edu.psu.geovista.app.pcp.plot.control.tools.BasicTool;
import edu.psu.geovista.app.plot.axis.*;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;

public class AxisRangeCfg2 extends BasicCfg {
    public static final String Property_ActiveAxisChange="paac";
    public static final String Property_ResetAxisRange="prar";


    // End of variables declaration

    MTYAxis axisConfigurer;
    YAxis sampleAxis; // 
    AxisList axisList;
    AxisShowRangeTool ashCmd;
    Hashtable zoomtables;//=new Hashtable();
    boolean initFinished=false;

    public AxisRangeCfg2() {
        initComponents(null) ;
        initCustomize();
    }
    //do customized init in addition to initComponents

    public AxisRangeCfg2(ConfigManager owner) {
        this.owner =owner;
        this.axisList =owner.getTargetUI().getPlot().getYaxisList() ;
        ashCmd=(AxisShowRangeTool) owner.getCmd(BasicTool.AxisShowRangeT );
        //this.axisList =axisList;
        this.addComponentListener(this); // 
        ArrayList names = axisList.getSortAxisNameList();
        initComponents( names);   //todo   it should be a table
        initCustomize();
    }

    private void initCustomize(){
        axisConfigurer.addPropertyChangeListener(new RangeMonitor());
        zoomtables=new Hashtable();

    }

    public void selectVariable(String vname){
        this.axisNameList.setSelectedValue(vname,true);
    }

    /*******************************************************************************************************
     *                GUI
     *******************************************************************************************************/
    protected void initValue() {

        ArrayList nameList=axisList.getSortAxisNameList();
        //if(nameList!=null&&nameList.size() >0)
        this.axisNameList.setListData(nameList.toArray() ); //update after hide an axis
        // 
        initFinished=true;
    }
    /**
     *  
     */
    public void updateView() {
        int selectedIndex = axisNameList.getSelectedIndex();
        this.initValue() ;
        if(selectedIndex>=0){
            axisNameList.setSelectedIndex(selectedIndex);
        }
       // this.updateOnSelectedAxisChange() ;//todo temp remove to see performance
    }
    private void updateOnSelectedAxisChange(){





        if(axisNameList.getSelectedValues()==null||axisNameList.getSelectedValues().length ==0){

            YAxis axis=(YAxis) this.axisList.getIndexSortAxisList().get(0);
            this.axisNameList.setSelectedValue(axis.getName() ,true);
        }
        Object[] names=axisNameList.getSelectedValues();
        setActAxisGroup(names); //The method will set sampleAxis

        //System.out.println("sampleAxis.tick:"+sampleAxis.getTickRange().getMin() +","+sampleAxis.getTickRange().getMax() );
        axisConfigurer.setTargetAxis(sampleAxis.cloneConfigAxis()); //sampleAxis set by  setActAxisGroup(names)


        Range targetTickR=axisConfigurer.getTargetAxisTickRange();
        Range targetShowR=axisConfigurer.getTargetAxisShowRange() ;
        Range cfgTickR=axisConfigurer.getTickRange() ;

        String ttrmax=String.valueOf(targetTickR.getMax()) ;
        String ttrmin=String.valueOf(targetTickR.getMin());
        String tsrmax=String.valueOf(targetShowR.getMax() );
        String tsrmin=String.valueOf(targetShowR.getMin() );
        String ctrmax=String.valueOf(cfgTickR.getMax() );
        String ctrmin=String.valueOf(cfgTickR.getMin() );

        this.tickMax.setText(ttrmax);
        this.showMin.setText(ttrmin);
        this.showMax.setText(tsrmax);
        this.tickMin.setText(tsrmin);

        //todo
        /* this.cfgTickMin.setText(ctrmin);
        this.cfgTickMax.setText(ctrmax);*/

        //keep the zoom value for each axis.
        //  
        Object selectedAxis = this.axisNameList.getSelectedValue();
        int selectedIndex = axisNameList.getSelectedIndex();
        //System.out.println("selected value:"+selectedAxis);
        Integer zoomvalue = null;
        if (selectedAxis!=null) {
            zoomvalue = (Integer) this.zoomtables.get(selectedAxis);
        }
        //System.out.println("zoom value:"+zoomvalue);
        int zv=this.zoomSlider.getMaximum() ;
        if(zoomvalue!=null){
            zv=zoomvalue.intValue() ;
        }
        //todo: notwork, since upon select a item, multiple calls are involved and eventually zv is set 100 again
        zoomSlider.setValue(zv);
        //this.zoomCfgAxis(zoomSlider);//todo  remove it temp since it cause serious performance problem when work with large data set( election_2)

    }

    private JList createNameList(ArrayList axisNameList) {
        final JList anl;

        anl= new JList(axisNameList.toArray());
        anl.setSelectedIndex(0);
        anl.addListSelectionListener(new ListSelectionListener() {
            //get event upon change selection on the JList
            public void valueChanged(ListSelectionEvent e) {
                //System.out.println("select changed");
                //todo why called multiple times upon select a item
                axisNameList1ValueChanged(e);
            }
        });

        return anl;
    }

    public void setSampleAxis(YAxis actAxis) {
        this.sampleAxis =actAxis;// ;
        //this.initValue() ;
        //this.firePropertyChange(Property_ActiveAxisChange,null,actAxis);
        //  axisConfigurer.setTargetAxis(actAxis.cloneConfigAxis());
        //  this.axisNameList.setSelectedValue(actAxis.getName(),true);
        //System.out.println("Select:"+this.axisNameList.getSelectedIndex() +" name :"+axisNameList.getSelectedValue() );
        //System.out.println("");

    }


    /*******************************************************************************************************
     *                Event
     *******************************************************************************************************/
    private void cfgTickChange(){

        /* String smax=this.cfgTickMax.getText() ;
        String smin=this.cfgTickMin.getText() ;
        float max=Validator.getNumberByText(smax,this);
        float min=Validator.getNumberByText(smin,this);

        this.axisConfigurer.setTickRange(new Extreme(max,min));
        repaint();*/
    }
    // Act on change to axisNameList's selection
    private void axisNameList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {
        Object source = evt.getSource();
        //System.out.println("Name list source:"+source.hashCode());
        this.updateOnSelectedAxisChange() ;

    }
    private void resetBtnAction() {
        this.ashCmd.resetRanges() ;
        this.firePropertyChange(Property_ResetAxisRange,null,null);//no use?
        this.initValue() ;//update list => config page repainted.
    }
    /* public void addSelectAxisListener(ListSelectionListener l) {
    this.axisNameList.addListSelectionListener(l);
    }*/
    public void addAxisRangeChangeListener() {
    }

    private void updateTTickValue(){
        float tmin =0;
        float tmax =0;
        try {
            tmin = Float.valueOf(tickMin.getText()).floatValue();
            tmax = Float.valueOf(tickMax.getText()).floatValue();
            /*Extreme cfgTickRange=axisConfigurer.getTickRange() ;
            if (tmin<cfgTickRange.getMin() ){
            axisConfigurer.setTickRange(new Extreme(cfgTickRange.getMax(),tmin));
            }
            if(tmax>cfgTickRange.getMax() ){
            axisConfigurer.setTickRange(new Extreme(tmax,cfgTickRange.getMin()));
            }*/
            Range tickRange=new Range(tmax,tmin);
            axisConfigurer.setTargetAxisTickRange(tickRange);

        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(AxisRangeCfg2.this,"Must enter a number ");
        }

    }
    private void updateShowRange(){
        float min=0 ;float max=0 ;
        try {
            min = Float.valueOf(showMin.getText()).floatValue();
            max = Float.valueOf(showMax.getText()).floatValue();


            Range showRange=new Range(0,0);
            showRange.setExtreme( axisConfigurer.getTargetAxisShowRange());
            Range dataRange=axisConfigurer.getTickRange() ;


            float datamin = dataRange.getMin();
            float datamax = dataRange.getMax();
            String dataRangeSt="["+datamin+","+datamax+"]";
            StringBuffer errsb=new StringBuffer();
            if (min<datamin ||min>datamax ){
                errsb.append("Min value of Filter Range must within the Data Range ");
                errsb.append(dataRangeSt);
                errsb.append("\n");
            }
            if (max<datamin ||max>datamax ){

                errsb.append("Max value of Filter Range must within the Data Range ");
                errsb.append(dataRangeSt);
            }

            if (errsb.length() >0){
                JOptionPane.showMessageDialog(AxisRangeCfg2.this,errsb.toString() );
                return;
            }

            showRange.setMin(min)  ;
            showRange.setMax(max);
            axisConfigurer.setTargetAxisShowRange(showRange);
            //System.out.println(tickMin.getText());
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(AxisRangeCfg2.this,"Must enter a number ");
        }
    }
    private void showMinActionPerformed(java.awt.event.ActionEvent evt) {
        updateShowRange();
        /* float min=0 ;
        try {
        min = Float.valueOf(showMin.getText()).floatValue();
        Extreme showRange=new Extreme(0,0);
        showRange.setExtreme( axisConfigurer.getTargetAxisShowRange());
        Extreme dataRange=axisConfigurer.getTickRange() ;
        if (min<dataRange.getMin() ||min>dataRange.getMax() ){
        JOptionPane.showMessageDialog(AxisRangeCfg2.this,"Must enter a number within tick range .");
        return;
        }
        showRange.setMin(min)  ;
        axisConfigurer.setTargetAxisShowRange(showRange);
        //System.out.println(tickMin.getText());
        } catch (NumberFormatException e) {
        JOptionPane.showMessageDialog(AxisRangeCfg2.this,"Must enter a number ");
        }*/
    }



    private void showMaxActionPerformed(java.awt.event.ActionEvent evt) {
        updateShowRange();
        /* float max=0 ;
        try {
        max = Float.valueOf(showMax.getText()).floatValue();
        Extreme showRange=new Extreme(0,0);
        showRange.setExtreme(axisConfigurer.getTargetAxisShowRange());
        Extreme dataRange=axisConfigurer.getTickRange() ;
        if (max<dataRange.getMin() ||max>dataRange.getMax() ){
        JOptionPane.showMessageDialog(AxisRangeCfg2.this,"Must enter a number within tick range .");
        return;
        }
        showRange.setMax(max)  ;
        axisConfigurer.setTargetAxisShowRange(showRange);
        //System.out.println(tickMin.getText());
        } catch (NumberFormatException e) {
        JOptionPane.showMessageDialog(AxisRangeCfg2.this,"Must enter a number ");
        }*/
    }


    private void reset() {
        Range dataRange=null;
        if(sampleAxis!=null)
            dataRange = this.sampleAxis.getDataRange();
        else
            dataRange = this.axisConfigurer.getDataRange();
        if (dataRange!=null){
            this.axisConfigurer.setTargetAxisShowRange(dataRange);
            this.axisConfigurer.setTargetAxisTickRange(dataRange);
            this.zoomSlider.setValue(zoomSlider.getMaximum() );
        }

        resetAllAxes();
    }
    /**
     * reset the tick range and show range = datarange for all axes
     */
    private void resetAllAxes() {
        AxisList axisList=this.axisList;
        for (Iterator iterator = axisList.iterator(); iterator.hasNext();) {
            YAxis axis = (YAxis) iterator.next();
            Range dataRange = axis.getDataRange();
            axis.setTickRange(dataRange);
            axis.setShowRange(dataRange);

        }
    }

    /*******************************************************************************************************
     *              controll  logic functions
     *******************************************************************************************************/
    /**
     *
     * @param ans axis names
     */
    private void setActAxisGroup(Object[] ans){
        if(ans==null||ans.length <=0){
            ashCmd.setActiveAxisGroup(null);
        }
        //Object[] ans=(Object[]) evt.getNewValue() ;

        YAxis[] activeAxisGroup=new YAxis[ans.length];
        for (int j=0;j<ans.length ;j++){
            YAxis ax=this.axisList.getAxis((String)ans[j]);
            if(ax!=null)
                activeAxisGroup[j]=ax;
            else{
                //throw new NullPointerException("ActiveAxisGroup can't be null");
                //System.out.println("bug 
                // 
            }

        }

        YAxis sampleAxis = this.createSampleAxis(activeAxisGroup);
        Range e=sampleAxis.getDataRange() ;
        this.setSampleAxis(sampleAxis);
        //this.setSampleAxis(this.createSampleAxis(activeAxisGroup));
        ashCmd.setActiveAxisGroup(activeAxisGroup);
    }
    /**
     * set sampleAxis's data range equal to the extreme of the activeAxisGroup
     * @param activeAxisGroup
     */
    private YAxis createSampleAxis(YAxis[] activeAxisGroup) {


        YAxis ax=new YAxis();
        if (activeAxisGroup.length ==1){
            YAxis tmp=activeAxisGroup[0];
            if(tmp==null) return new YAxis();
            //Extreme e=tmp.getDataRange() ;
            //System.out.println("sample ax.setTickRange as "+tmp.getName()+":"+tmp.getTickRange().getMin()+","+tmp.getTickRange().getMax());
            ax.setDataRange(tmp.getDataRange() ) ;
            ax.setTickRange(tmp.getTickRange() );
            ax.setShowRange(tmp.getShowRange() );
            //Extreme e2=ax.getDataRange() ;
            //Extreme e3=ax.getDataRange() ;

        }
        else{
            ax.setDataRange(findRangeExtremeOfAxisGroup(activeAxisGroup,0));
            ax.setShowRange(findRangeExtremeOfAxisGroup(activeAxisGroup,-1));
            ax.setTickRange(findRangeExtremeOfAxisGroup(activeAxisGroup,1));

        }
        return ax;
    }
    /**
     * find max and min out of all the dataRange of given axis
     * @param axList
     * @return
     */
    private Range findRangeExtremeOfAxisGroup(YAxis[] axList,int mode){
        int len=axList.length ;
        float[] mins=new float[len];
        float[] maxs=new float[len];

        for (int i=0;i<len;i++){
            YAxis ax=axList[i];
            Range range=null;
            if(mode==0){
                range=ax.getDataRange() ;
            }
            else if(mode<0){
                range=ax.getShowRange() ;
            }
            else{
                range=ax.getTickRange() ;
            }
            mins[i]=range.getMin() ;
            maxs[i]=range.getMax() ;
        }
        Arrays.sort(mins);
        Arrays.sort(maxs);
        float min=mins[0];
        float max=maxs[len-1];
        Range ex=new Range(max,min);
        return ex;
    }
    private ArrayList getAxisbyNames(Object[] names) {
        if (names==null||names.length<=0) return null;
        ArrayList axs=new ArrayList(names.length );
        for (int i=0;i<names.length ;i++){
            String n=(String) names[i];
            YAxis ax=this.axisList.getAxis(n);
            axs.add(ax);
        }
        return axs;
    }


    public class RangeMonitor implements PropertyChangeListener{
        public void propertyChange(PropertyChangeEvent evt) {
            if (initFinished==false)return;
            String pn=evt.getPropertyName();

            if (pn!=null &&pn.equals(BasicAxis.PTickRange ) ){
                final Range range=(Range)evt.getNewValue() ;
                float min=range.getMin() ;
                float max=range.getMax() ;
                tickMax.setText(String.valueOf(max));
                tickMin.setText(String.valueOf(min));
                if(ashCmd!=null)  {//it is null when run test
                    //ashCmd.updateTickRange(range) ;
                    // 
                    SwingUtilities.invokeLater(new Runnable(){

                        public void run() {
                            ashCmd.updateTickRange(range) ; // 
                        }
                    });
                }
                //AxisRangeCfg.this.firePropertyChange(BasicAxis.PTickRange,null,range);
            }
            else if(pn!=null &&pn.equals(BasicAxis.PShowRange ) ){
                final Range range=(Range)evt.getNewValue() ;
                float min=range.getMin() ;
                float max=range.getMax() ;
                showMax.setText(String.valueOf(max));
                showMin.setText(String.valueOf(min));
                if(ashCmd!=null)  {//it is null when run test
                    //ashCmd.updateShowRange(range) ;
                    // 
                    SwingUtilities.invokeLater(new Runnable(){

                        public void run() {
                            ashCmd.updateShowRange(range) ;// 
                        }
                    });
                }
                //AxisRangeCfg.this.firePropertyChange(BasicAxis.PShowRange,null,range);
            }
        }

    }

    public MTYAxis getAxisConfigurer() {
        return axisConfigurer;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor
     */
    private void initComponents(ArrayList axisNames) {
        java.awt.GridBagConstraints gridBagConstraints;

        jTable1 = new javax.swing.JTable();
        MainP = new javax.swing.JPanel();
        LeftPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        //axisNameList = new javax.swing.JList();
        if (axisNames !=null){
            axisNameList=this.createNameList(axisNames );
        }
        else{
            axisNameList = new javax.swing.JList();
        }
        CenterPanel = new javax.swing.JPanel();
        RangePanel = new javax.swing.JPanel();
        showMax = new javax.swing.JTextField();
        tickMin = new javax.swing.JTextField();
        tickMax = new javax.swing.JTextField();
        showMin = new javax.swing.JTextField();
        minLb = new javax.swing.JLabel();
        maxLb = new javax.swing.JLabel();
        FilterlabelP = new javax.swing.JPanel();
        stLL = new javax.swing.JLabel();
        imageLL = new javax.swing.JLabel();
        DatalabelP = new javax.swing.JPanel();
        imageLR = new javax.swing.JLabel();
        stLR = new javax.swing.JLabel();
        AxisPanel = new javax.swing.JPanel();
        //jLabel1 = new javax.swing.JLabel();
        axisConfigurer=new MTYAxis();
        axisConfigurer.addPropertyChangeListener(new AxisRangeCfg2.RangeMonitor());
        axisConfigurer.setActiveSize(300);

        zoomSlider = new javax.swing.JSlider();
        zoomSlider.setValue(zoomSlider.getMaximum() );     //jin
        ControlP = new javax.swing.JPanel();
        applyBtn = new javax.swing.JButton();
        resetBtn = new javax.swing.JButton();
        closeBtn = new javax.swing.JButton();

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
                new Object [][] {

                    {null, null},
                    {null, null}
                },
                new String [] {
                    "Title 1", "Title 2"
                }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });

        setLayout(new java.awt.BorderLayout());

        MainP.setLayout(new java.awt.GridBagLayout());

        LeftPanel.setLayout(new java.awt.BorderLayout());

        /*axisNameList.setModel(new javax.swing.AbstractListModel() {
        String[] strings = { "asddfasddffasdfasfasfasfsadfsdafsadf", "asdf", "asdf", "asdf", "asd", "fsa", "asdf", "asf", "asdsf", "asdf", "asdf", "as", "dffa", "sf", "as", "fas", "f", "asf", "as", "f", "asddf", "asd", "fas", "df", "asdf", "sad", "as", "as", "df", "asf", "as", "fas", "f", "assf", "as", "fas", "f", "saf", "sadsd", "fsad", "f", "dsf", "sdf", "sdf", "s", "fsd", "f", "sdf", "sd", "fsa", "f", "s", "sf", "sddf" };
        public int getSize() { return strings.length; }
        public Object getElementAt(int i) { return strings[i]; }
        });*/
        jScrollPane1.setViewportView(axisNameList);

        LeftPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        MainP.add(LeftPanel, gridBagConstraints);

        CenterPanel.setLayout(new java.awt.BorderLayout());

        RangePanel.setLayout(new java.awt.GridBagLayout());

        showMax.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showMaxActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 36;
        gridBagConstraints.ipady = 2;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
        gridBagConstraints.weightx = 4.0;
        RangePanel.add(showMax, gridBagConstraints);

        tickMin.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                //showMinActionPerformed(evt);
                AxisRangeCfg2.this.updateTTickValue();
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 27;
        gridBagConstraints.ipady = 4;
        gridBagConstraints.weightx = 4.0;
        RangePanel.add(tickMin, gridBagConstraints);

        tickMax.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                tickMaxActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 26;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.weightx = 4.0;
        RangePanel.add(tickMax, gridBagConstraints);

        showMin.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                //tickMinActionPerformed(evt);
                showMinActionPerformed(evt);

            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 35;
        gridBagConstraints.ipady = 1;
        gridBagConstraints.insets = new java.awt.Insets(4, 0, 4, 0);
        gridBagConstraints.weightx = 4.0;
        RangePanel.add(showMin, gridBagConstraints);

        minLb.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        minLb.setFont(new java.awt.Font("MS Sans Serif", 1, 11));
        minLb.setText("min");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.ipadx = 21;
        gridBagConstraints.ipady = 7;
        gridBagConstraints.weightx = 1.0;
        RangePanel.add(minLb, gridBagConstraints);

        maxLb.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        maxLb.setFont(new java.awt.Font("MS Sans Serif", 1, 11));
        maxLb.setText("max");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.ipadx = 16;
        gridBagConstraints.ipady = 5;
        gridBagConstraints.weightx = 1.0;
        RangePanel.add(maxLb, gridBagConstraints);

        FilterlabelP.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER ));

        stLL.setFont(new java.awt.Font("MS Sans Serif", 1, 14));
        stLL.setForeground(MTYAxis.THUMB_COLOR_WEST);
        stLL.setText("Filter Range");
        stLL.setToolTipText("You can hide the strings with value out of the axis's filter range");
        FilterlabelP.add(stLL);

        //imageLL.setText("<");
        FilterlabelP.add(imageLL);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 18;
        RangePanel.add(FilterlabelP, gridBagConstraints);

        DatalabelP.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER));

        // imageLR.setText(">");
        DatalabelP.add(imageLR);
        stLR.setFont(new java.awt.Font("MS Sans Serif", 1, 14));
        stLR.setForeground(MTYAxis.THUMB_COLOR_EAST);
        stLR.setText("Data Range");
        stLR.setToolTipText("This is the min/max value of the axis on the plot");
        DatalabelP.add(stLR);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 9;
        RangePanel.add(DatalabelP, gridBagConstraints);

        CenterPanel.add(RangePanel, java.awt.BorderLayout.SOUTH);

        //jLabel1.setText("jLabel1");
        AxisPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                AxisPanelComponentResized(evt);
            }
        });
        AxisPanel.setLayout(new BorderLayout());
        //AxisPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 10));
        AxisPanel.add(axisConfigurer);
        AxisPanel.add(new JPanel(),BorderLayout.NORTH );
        /* Not work, axisConfigurer won't show up
        AxisPanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 0);
        AxisPanel.add(axisConfigurer, gridBagConstraints);
        axisConfigurer.setBounds(10,10,40,300);*/



        CenterPanel.add(AxisPanel, java.awt.BorderLayout.CENTER);

        zoomSlider.setSnapToTicks(true);
        zoomSlider.setBorder(new javax.swing.border.TitledBorder(null, "Zoom", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("MS Sans Serif", 1, 14)));//new javax.swing.border.TitledBorder("Zoom"));
        zoomSlider.setName("Zoom");
        zoomSlider.setToolTipText(" Recommend to zoom in when you want to more space to show the values between a pair of handlers.");
        zoomSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                zoomSliderStateChanged(evt);
            }
        });
        CenterPanel.add(zoomSlider, java.awt.BorderLayout.NORTH);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        MainP.add(CenterPanel, gridBagConstraints);

        add(MainP, java.awt.BorderLayout.CENTER);

        ControlP.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        ControlP.setBorder(new javax.swing.border.EtchedBorder());
        applyBtn.setText("Apply");
        applyBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                applyBtnActionPerformed(evt);
            }
        });

        ControlP.add(applyBtn);

        resetBtn.setText("Reset");
        resetBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetBtnActionPerformed(evt);
            }
        });

        ControlP.add(resetBtn);

        closeBtn.setText("Close");
        closeBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeBtnActionPerformed(evt);
            }
        });

        ControlP.add(closeBtn);

        add(ControlP, java.awt.BorderLayout.SOUTH);

    }

    private void resizeAxis(int panelHeight) {
        this.axisConfigurer.setActiveSize(panelHeight-40);
    }
    /***
     *  
     *  
     *  
     * @param evt
     */
    private void zoomSliderStateChanged(javax.swing.event.ChangeEvent evt) {

        JSlider slider = (JSlider) evt.getSource();
        zoomCfgAxis(slider);


        //System.out.println("");
    }

    private void zoomCfgAxis(JSlider slider) {

        // 
        float smin = slider.getMinimum();
        float smax = slider.getMaximum();
        int value = slider.getValue();
        float percentage=(value-smin)/(smax-smin);
        //System.out.println("percentage:"+percentage);
        // 
        Range dataRange = axisConfigurer.getDataRange();
        // 
        float datamin=(dataRange.getMin()*percentage);
        float datamax=(dataRange.getMax()*percentage);

        //This is the values of the 2 handlers. It defines a range that user interest
        Range tickRange = this.axisConfigurer.getTargetAxisTickRange();
        // 
        float tickmin = tickRange.getMin();
        float tickmax = tickRange.getMax();

        //calculate new tick range for configure axis after zoom in
        // 
        float dymax=(datamax-tickmax)*percentage;
        float sugmax=tickmax+dymax;   //sugmax: suggested max tick value of configure axis

        float dymin=(datamin-tickmin)*percentage;
        float sugmin=tickmin+dymin;


        // 
        // 
        float min=Math.min(tickmin,sugmin);
        float max=Math.max(tickmax, sugmax);

        axisConfigurer.setTickRange(new Range(max,min));

        Object selectAxis = this.axisNameList.getSelectedValue();
        Integer Ivalue=new Integer(value);
        if(selectAxis!=null&&Ivalue!=null)
            this.zoomtables.put(selectAxis,Ivalue);
    }

    private void zoomSliderStateChanged1(javax.swing.event.ChangeEvent evt) {
        // 
        JSlider slider = (JSlider) evt.getSource();
        float smin = slider.getMinimum();
        float smax = slider.getMaximum();
        int value = slider.getValue();
        float percentage=(value-smin)/(smax-smin);

        // 
        Range dataRange = axisConfigurer.getDataRange();
        float datamin = dataRange.getMin();
        float datamax = dataRange.getMax();

        // 
        Range tickRange = this.axisConfigurer.getTargetAxisTickRange();
        //This is the values of the 2 handlers. It defines a range that user interest
        float tmin = tickRange.getMin();
        float tmax = tickRange.getMax();

        float dmax=tmax-datamax;
        float dmin=tmin-datamin;




        float sugmin=datamin+dmin*percentage;

        float sugmax=datamax+(dmax*percentage);

        // 
        float min=Math.min(tmin,sugmin);
        float max=Math.max(tmax, sugmax);

        axisConfigurer.setTickRange(new Range(max,min));
        //System.out.println("");
    }


    private void AxisPanelComponentResized(java.awt.event.ComponentEvent evt) {
        Dimension size = evt.getComponent().getSize();
        if(size!=null)
            this.resizeAxis(size.height );
    }
    private void closeBtnActionPerformed(java.awt.event.ActionEvent evt) {
        if(owner!=null)
            this.owner.close();
    }

    private void resetBtnActionPerformed(java.awt.event.ActionEvent evt) {
        reset();
    }

    private void applyBtnActionPerformed(java.awt.event.ActionEvent evt) {
        this.updateTTickValue();
        updateShowRange();
        //showMinActionPerformed(null);
        //showMaxActionPerformed(null);
    }
    private void tickMaxActionPerformed(java.awt.event.ActionEvent evt) {
        updateTTickValue();
    }

    private void tickMinActionPerformed(java.awt.event.ActionEvent evt) {
        updateTTickValue();
    }


    // Variables declaration - do not modify
    private javax.swing.JPanel AxisPanel;
    private javax.swing.JPanel CenterPanel;
    private javax.swing.JPanel ControlP;
    private javax.swing.JPanel DatalabelP;
    private javax.swing.JPanel FilterlabelP;
    private javax.swing.JPanel LeftPanel;
    private javax.swing.JPanel MainP;
    private javax.swing.JPanel RangePanel;
    private javax.swing.JButton applyBtn;
    private javax.swing.JList axisNameList;
    private javax.swing.JButton closeBtn;
    private javax.swing.JLabel imageLL;
    private javax.swing.JLabel imageLR;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    private javax.swing.JLabel maxLb;
    private javax.swing.JLabel minLb;
    private javax.swing.JButton resetBtn;
    private javax.swing.JTextField showMax;
    private javax.swing.JTextField tickMin;
    private javax.swing.JLabel stLL;
    private javax.swing.JLabel stLR;
    private javax.swing.JTextField tickMax;
    private javax.swing.JTextField showMin;
    private javax.swing.JSlider zoomSlider;
    // End of variables declaration



}

